[Android] OkHTTP + Retrofit + RxAndroid で REST クライアントを実装する
REST 処理を扱いやすく実装する
Android の REST クライアントのネットワーク処理と非同期処理について、最近流行っている OkHTTP と Retrofit と RxAndroid の組み合わせを使ってみました。これらはそれぞれ次のような機能を提供するライブラリです。
OkHTTP
- HTTP クライアント用のライブラリ
- HTTP2/SPDY などのプロトコルにも対応
- HTTP ヘッダーのポリシーに準拠したローカルキャッシュの実装
Retrofit
- REST クライアント用のライブラリ
- アノテーションでメソッドやパラメータを指定可能
- 通信処理は抽象化されているため自由に実装可能
RxAndroid
- RxJava の Android 版
- リアクティブプログラミングを Android で実装するためのライブラリ
- イベントベースで遅延実行や非同期コールバックなどを実装可能
なお、Retrofit が OkHTTP と RxAndroid の架け橋になってくれるため、組み合わせてシンプルに記述可能になります。
導入
まずはこれら3つのライブラリを Android プロジェクトに導入しましょう。
dependencies { compile 'com.squareup.okhttp:okhttp:2.4.0' compile 'com.squareup.retrofit:retrofit:1.9.0' compile 'io.reactivex:rxandroid:0.24.0' }
実装する
準備が整いましたので、実装していきましょう。OpenWeatherMap の JSON を GET してくるサンプルを実装したいと思います。
Entity クラスの作成
今回は JSON のパーサに Gson を使います。ということでまずはエンティティクラスを作りましょう。以下は余分なプロパティを省略していますのでご容赦ください。
package jp.classmethod.sample.restsample; import java.util.List; public class WeatherEntity { public String base; public List weather; public class Weather { public int id; public String main; public String description; public String icon; } }
REST インターフェースの作成
次に、REST クライアントのインターフェースを作成します。メソッド名を決めてアノテーションを追加するだけです。
package jp.classmethod.sample.restsample; import retrofit.http.GET; import retrofit.http.Path; import retrofit.http.Query; import rx.Observable; public interface WeatherApi { @GET("/data/2.5/{name}") public Observable get(@Path("name") String name, @Query("q") String q); }
非同期処理を実行する
あとは RestAdapter をインスタンス化し、Observer で Subscribe するだけです。以下は Activity でやっていますがもちろん Fragment でも構いません。
package jp.classmethod.sample.restsample; import android.os.Bundle; import android.support.v7.app.AppCompatActivity; import android.util.Log; import android.view.Menu; import android.view.MenuItem; import android.widget.TextView; import com.google.gson.FieldNamingPolicy; import com.google.gson.Gson; import com.google.gson.GsonBuilder; import com.google.gson.internal.bind.DateTypeAdapter; import java.util.Date; import retrofit.RestAdapter; import retrofit.android.AndroidLog; import retrofit.converter.GsonConverter; import rx.Observer; import rx.android.schedulers.AndroidSchedulers; import rx.schedulers.Schedulers; public class MainActivity extends AppCompatActivity { private static final String TAG = MainActivity.class.getSimpleName(); @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_main); // JSONのパーサー Gson gson = new GsonBuilder() .setFieldNamingPolicy(FieldNamingPolicy.LOWER_CASE_WITH_UNDERSCORES) .registerTypeAdapter(Date.class, new DateTypeAdapter()) .create(); // RestAdapterの生成 RestAdapter adapter = new RestAdapter.Builder() .setEndpoint("http://api.openweathermap.org") .setConverter(new GsonConverter(gson)) .setLogLevel(RestAdapter.LogLevel.FULL) .setLog(new AndroidLog("=NETWORK=")) .build(); // 非同期処理の実行 adapter.create(WeatherApi.class).get("weather", "Tokyo,jp") .subscribeOn(Schedulers.newThread()) .observeOn(AndroidSchedulers.mainThread()) .subscribe(new Observer() { @Override public void onCompleted() { Log.d("MainActivity", "onCompleted()"); } @Override public void onError(Throwable e) { Log.e("MainActivity", "Error : " + e.toString()); } @Override public void onNext(WeatherEntity weather) { Log.d("MainActivity", "onNext()"); if (weather != null) { ((TextView) findViewById(R.id.text)).setText(weather.weather.get(0).main); } } }); } }
以上で終わりです!アプリを起動してみると Rain と出ました。梅雨ですね。
まとめ
以上、簡単なサンプルでした。
これらのライブラリの開発に参加している JakeWharton さんすごい!と思いました。